package com.bringspring.system.base.controller;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.bringspring.common.base.ActionResult;
import com.bringspring.common.base.UserInfo;
import com.bringspring.common.util.*;
import com.bringspring.system.base.entity.SysConfigEntity;
import com.bringspring.system.base.model.dingding.DingDeptModel;
import com.bringspring.system.base.model.dingding.DingUserIdModel;
import com.bringspring.system.base.model.dingding.DingUserModel;
import com.bringspring.system.base.model.systemconfig.SysConfigCropModel;
import com.bringspring.system.base.service.SysConfigService;
import com.bringspring.system.base.util.aes.QyWxConfig;
import com.bringspring.system.message.entity.SynThirdInfoEntity;
import com.bringspring.system.message.service.SynThirdDingTalkService;
import com.bringspring.system.message.service.SynThirdInfoService;
import com.bringspring.system.message.service.SynThirdQyService;
import com.bringspring.system.message.util.SynThirdConsts;
import com.bringspring.system.message.util.SynThirdTotal;
import com.bringspring.system.permission.entity.OrganizeEntity;
import com.bringspring.system.permission.entity.RoleEntity;
import com.bringspring.system.permission.entity.UserEntity;
import com.bringspring.system.permission.service.OrganizeService;
import com.bringspring.system.permission.service.RoleService;
import com.bringspring.system.permission.service.UserService;
import com.bringspring.system.permission.util.BaseDataUtil;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.request.OapiV2DepartmentGetRequest;
import com.dingtalk.api.request.OapiV2UserGetRequest;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.api.response.OapiV2DepartmentGetResponse;
import com.dingtalk.api.response.OapiV2UserGetResponse;
import com.dingtalk.open.app.api.GenericEventListener;
import com.dingtalk.open.app.api.OpenDingTalkStreamClientBuilder;
import com.dingtalk.open.app.api.message.GenericOpenDingTalkEvent;
import com.dingtalk.open.app.api.security.AuthClientCredential;
import com.dingtalk.open.app.stream.protocol.event.EventAckStatus;
import lombok.extern.slf4j.Slf4j;
import org.apdplat.word.segmentation.Word;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.bringspring.system.message.util.SynThirdConsts.*;
import static com.bringspring.system.permission.constant.PermissionConst.COMPANY;
import static com.bringspring.system.permission.constant.PermissionConst.SIMPLE_USER;
import static org.apdplat.word.tagging.PinyinTagging.process;

@Slf4j
public class DIngStream implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private UserProvider userProvider;
    @Autowired
    private SynThirdInfoService synThirdInfoService;
    @Autowired
    private SynThirdQyService synThirdQyService;
    @Autowired
    private SynThirdDingTalkService synThirdDingTalkService;
    @Autowired
    private OrganizeService organizeService;
    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private BaseDataUtil baseDataUtil;

    @Autowired
    QyWxConfig qyWxConfig;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        ApplicationContext context = event.getApplicationContext().getParent();
        try {
            this.dingStream();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 钉钉stream回调
     * 不带第三方错误定位判断的功能代码 20210604
     *
     * @return ignore
     */
    public void dingStream() throws Exception {

        SysConfigEntity dingCom = sysConfigService.getConfigByKeyName("dingCom");
        if (ObjectUtil.isNotNull(dingCom)) {
        List<SysConfigCropModel> jsonToList = JsonUtil.getJsonToList(String.valueOf(dingCom.getKeyValue()), SysConfigCropModel.class);
        List<SysConfigCropModel> collectCrop = jsonToList.stream().filter(v -> "dingqgbtl0pzm45qbonu".equals(v.getClientId())).collect(Collectors.toList());
        String corpId = collectCrop.get(0).getClientId();
        String corpSecret = collectCrop.get(0).getClientSecrent();
        OpenDingTalkStreamClientBuilder.custom().credential(new AuthClientCredential(corpId, corpSecret))
                //注册事件监听
                .registerAllEventListener(new GenericEventListener() {
                    public EventAckStatus onEvent(GenericOpenDingTalkEvent event) {
                        try {
                            //事件唯一Id
                            String eventId = event.getEventId();
                            //事件类型
                            String eventType = event.getEventType();
                            //事件产生时间
                            Long bornTime = event.getEventBornTime();
                            //获取事件体
                            JSONObject bizData = event.getData();
                            if ("org_dept_create".equals(eventType) || "org_dept_modify".equals(eventType)) {
                                orgChange(bizData, corpId);
                            } else if ("user_add_org".equals(eventType) || "user_modify_org".equals(eventType)) {
                                userChange(bizData, corpId);
                            }
                            //处理事件
                            process((List<Word>) bizData);
                            //消费成功
                            return EventAckStatus.SUCCESS;
                        } catch (Exception e) {
                            //消费失败
                            return EventAckStatus.LATER;
                        }
                    }
                }).build().start();
        }
    }

    public void userChange(JSONObject bizData, String corpId) throws Exception {
        //人员变更
        userAOD(JsonUtil.getJsonToBean(bizData, DingUserIdModel.class).getUserId().get(0), corpId);
    }

    public DingUserModel userAOD(String userId, String qyhCorpId) throws Exception {

        List<SynThirdInfoEntity> listThird = synThirdInfoService.getList(SynThirdConsts.THIRD_TYPE_QY, SynThirdConsts.DATA_TYPE_USER);

        List<RoleEntity> listByEnCode = roleService.getListByEnCode(SIMPLE_USER);
        UserInfo userInfo = userProvider.get();
        DingTalkClient clientUser = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get");
        OapiV2UserGetRequest reqUser = new OapiV2UserGetRequest();
        reqUser.setUserid(userId);
        OapiV2UserGetResponse rspUser = clientUser.execute(reqUser, dingAssisToken());
        DingUserModel map = JsonUtil.getJsonToBean(String.valueOf(JsonUtil.stringToMap(rspUser.getBody()).get("result")), DingUserModel.class);
        map.setDepartmentId(map.getDept_id_list().get(0));
        System.out.println(rspUser.getBody());
        //resultUserList.add(resultUser);

        UserEntity userEntity = new UserEntity();
        String userid = String.valueOf(map.getUserid());
        SynThirdInfoEntity synThirdInfoEntity = new SynThirdInfoEntity();
        // 账户用userID id
        if (!StringUtils.isNull(map.getUserid())) {
            List<SynThirdInfoEntity> first = listThird.stream().filter(n -> userid.equals(n.getThirdObjectId())).collect(Collectors.toList());
            if (!ObjectUtil.isEmpty(first)) {
                synThirdInfoEntity = first.get(0);
                if (null != synThirdInfoEntity) {
                    userEntity.setId(synThirdInfoEntity.getSystemObjectId());
                } else {
                    userEntity.setId(RandomUtil.uuId());
                    synThirdInfoEntity = new SynThirdInfoEntity();
                    synThirdInfoEntity.setId(RandomUtil.uuId());
                }
            }
        }
        // 判断是不是为空,需要挨个判断。
        if (!StringUtils.isNull(map.getName())) {
            userEntity.setRealName(map.getName().replaceAll("[^\u4e00-\u9fa5]", ""));
        }

        // 昵称
        if (!StringUtils.isNull(map.getNickname())) {
            userEntity.setNickName(map.getNickname());
        }
        // 账户用userID id
        if (!StringUtils.isNull(map.getUserid())) {
            userEntity.setAccount(map.getUserid());
        }
        if (!StringUtils.isNull(map.getDepartmentId())) {
            List<SynThirdInfoEntity> infoByThirdObjId = synThirdInfoService.getInfoByThirdObjIds(THIRD_TYPE_DING, DATA_TYPE_ORG, map.getDepartmentId()).stream().filter(v -> !ObjectUtil.isEmpty(v.getSystemObjectId())).collect(Collectors.toList());
            if (!ObjectUtil.isEmpty(infoByThirdObjId)) {
                userEntity.setOrganizeId(infoByThirdObjId.get(0).getSystemObjectId());
            } else {
                userEntity.setOrganizeId(map.getDepartmentId());
            }
        }
        if (!StringUtils.isNull(map.getMobile())) {
            userEntity.setMobilePhone(map.getMobile());
        }
        if (!StringUtils.isNull(map.getEmail())) {
            userEntity.setEmail(map.getEmail());
        }
        if (!StringUtils.isNull(map.getWork_place())) {
            userEntity.setPostalAddress(map.getWork_place());
        }
        userEntity.setGender(3);
        if (!StringUtils.isNull(map.getManager_userid())) {
            userEntity.setManagerId(map.getManager_userid());
        }
//                        if (!StringUtil.isNull(map.get("position"))) {
//                            userEntity.setPositionId(String.valueOf(map.get("position")));
//                        }
        //获取头像  微信企业没传，暂定为默认
        userEntity.setHeadIcon("/api/file/Image/userAvatar/001.png");
        userEntity.setEnabledMark(1);
        userEntity.setRoleId(listByEnCode.get(0).getId());
        // 自定义员工编号，根据组织id获取所属公司。
        OrganizeEntity orgInfo = organizeService.getInfo(qyhCorpId + map.getDepartmentId());
        if (ObjectUtil.isNotEmpty(orgInfo)) {
            OrganizeEntity companyInfo = organizeService.getInfo(orgInfo.getOrganizeId());
            if (!ObjectUtil.isEmpty(companyInfo)) {
                String enCode = companyInfo.getEnCode() + "Staff";
                String billNumber = baseDataUtil.getBillNumber(enCode, false);
                userEntity.setCode(billNumber);
            } else {
                String enCode = "RStaff";
                String billNumber = baseDataUtil.getBillNumber(enCode, false);
                userEntity.setCode(billNumber);
            }
        }
        List<SynThirdInfoEntity> infoByThirdObjIds = synThirdInfoService.getInfoByThirdObjIds(SynThirdConsts.THIRD_TYPE_DING, SynThirdConsts.DATA_TYPE_USER, map.getUserid());
        if (ObjectUtil.isEmpty(infoByThirdObjIds)) {
            userEntity.setId(qyhCorpId + map.getUserid());
            userService.createUser(userEntity);
            synThirdInfoEntity.setThirdObjectId(String.valueOf(map.getUserid()));
            synThirdInfoEntity.setSystemObjectId(userEntity.getId());
            synThirdInfoEntity.setThirdType(Integer.valueOf(SynThirdConsts.THIRD_TYPE_DING));
            synThirdInfoEntity.setDataType(Integer.valueOf(SynThirdConsts.DATA_TYPE_USER));
            synThirdInfoEntity.setSynState(SynThirdConsts.SYN_STATE_OK);
            synThirdInfoEntity.setCropId("dingqgbtl0pzm45qbonu");
            synThirdInfoEntity.setCreatorUserId(userInfo.getUserId());
            synThirdInfoEntity.setCreatorTime(DateUtil.getNowDate());
            synThirdInfoService.saveOrUpdate(synThirdInfoEntity);
        } else {
            //  编辑
            userEntity.setId(infoByThirdObjIds.get(0).getSystemObjectId());
            boolean update = userService.updateById(userEntity);
        }
        return null;
    }

    public void orgChange(JSONObject bizData, String cropId) throws Exception {
        //部门变更
        JsonUtil.getJsonToBean(bizData, DingUserIdModel.class);
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/get");
        OapiV2DepartmentGetRequest req = new OapiV2DepartmentGetRequest();
        req.setDeptId(JsonUtil.getJsonToBean(bizData, DingUserIdModel.class).getDeptid().get(0));
        OapiV2DepartmentGetResponse rsp = client.execute(req, dingAssisToken());
        System.out.println(rsp.getBody());
        DingDeptModel resultDepart = JsonUtil.getJsonToBean(String.valueOf(JsonUtil.stringToMap(rsp.getBody()).get("result")), DingDeptModel.class);
        List<DingDeptModel> resultDepartList = new ArrayList<>();
        resultDepartList.add(resultDepart);
        orgAOD(resultDepartList, cropId);
    }

    public ActionResult orgAOD(List<DingDeptModel> resultDepart, String cropId) {
        // 有的新增，没有的编辑。
        String organize = "";
        for (DingDeptModel v : resultDepart) {
            List<SynThirdInfoEntity> infoByThirdObjIds = synThirdInfoService.getInfoByThirdObjIds(THIRD_TYPE_DING, DATA_TYPE_ORG, v.getDept_id());
            OrganizeEntity entityAdd = new OrganizeEntity();
            entityAdd.setId(cropId + v.getDept_id());
            entityAdd.setFullName(v.getName());
            entityAdd.setParentId(cropId + v.getParent_id());
//            entityAdd.setCategory("department");
            if ("1".equals(String.valueOf(v.getDept_id()))) {
                entityAdd.setCategory("company");
                entityAdd.setEnCode("R");
//                    organizeEntityQy.setParentId(!ObjectUtil.isEmpty(config.getOrgParent()) ? config.getOrgParent() : "0");
                entityAdd.setParentId("0");
                organize = cropId + v.getDept_id();
            } else {
                entityAdd.setCategory("department");
            }
            entityAdd.setOrganizeId(cropId + v.getParent_id());
            if (ObjectUtil.isEmpty(infoByThirdObjIds)) {
                // 新增
                synThirdQyService.createOrgan(entityAdd);
                SynThirdInfoEntity synThirdInfoEntity = new SynThirdInfoEntity();
                synThirdInfoEntity.setThirdObjectId(v.getDept_id());
                synThirdInfoEntity.setSystemObjectId(entityAdd.getId());
                synThirdInfoEntity.setThirdType(Integer.valueOf(THIRD_TYPE_DING));
                synThirdInfoEntity.setDataType(Integer.valueOf(DATA_TYPE_ORG));
                synThirdInfoEntity.setSynState(SynThirdConsts.SYN_STATE_OK);
                synThirdInfoEntity.setCreatorUserId(userProvider.get().getUserId());
                synThirdInfoEntity.setCreatorTime(DateUtil.getNowDate());
                synThirdInfoEntity.setId(RandomUtil.uuId());
                synThirdInfoEntity.setCropId(cropId);
                synThirdInfoService.saveOrUpdate(synThirdInfoEntity);
            } else {
                // 编辑
                OrganizeEntity entityEdit = new OrganizeEntity();
                entityEdit.setId(infoByThirdObjIds.get(0).getSystemObjectId());
                organizeService.update(entityAdd.getId(), entityAdd);
            }
        }
        //获取结果
        SynThirdTotal synThirdTotal = synThirdInfoService.getSynTotal(SynThirdConsts.THIRD_TYPE_DING, DATA_TYPE_ORG);
        setOrganizeCode();
        setOrganizedTree();
        return ActionResult.success(synThirdTotal);
    }

    public String dingAssisToken() throws Exception {
        DingTalkClient clientToken = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
        OapiGettokenRequest req = new OapiGettokenRequest();
        req.setAppkey("dingqgbtl0pzm45qbonu");
        req.setAppsecret("299RRMGBuD-Hsw9LE76DzJi-ApKmq3MABXm-tS8-plFFt189RrSJi_qB0U7tAot1");
        req.setHttpMethod("GET");
        OapiGettokenResponse rsp = clientToken.execute(req);
        System.out.println(rsp.getBody());
        Map<String, Object> stringObjectMap = JsonUtil.stringToMap(rsp.getBody());
        if (!stringObjectMap.containsKey("access_token")) {
            throw new Exception("获取钉钉access_token失败");
        }
        return String.valueOf(stringObjectMap.get("access_token"));
    }

    public void setOrganizeCode() {
        // 查询编码为空的，然后在设置编码
        List<OrganizeEntity> orgListCodeNull = organizeService.getOrgListCodeNull();
        if (ObjectUtil.isNotEmpty(orgListCodeNull)) {
            orgListCodeNull.stream().forEach(item -> {
                if (!"company".equals(item.getCategory())) {
                    setCode(item);
                }
            });
        }

    }

    public void setCode(OrganizeEntity entity) {
        // 设置编码
        //父级编码为空的继续查询,直到父级编码不为空
        OrganizeEntity parentEntity = organizeService.getInfo(entity.getParentId());
        if (!ObjectUtil.isEmpty(parentEntity)) {
            if (ObjectUtil.isNotEmpty(parentEntity.getEnCode())) {
                List<OrganizeEntity> parentIdList = organizeService.getParentIdListAsc(entity.getParentId());
                if (ObjectUtil.isNotEmpty(parentIdList) && ObjectUtil.isNotEmpty(parentIdList.get(0).getEnCode())) {
                    String enCode1 = parentIdList.get(0).getEnCode();
                    String ul = enCode1.replaceAll("[a-zA-Z]", "");
                    //  String ul = parentEntity.getEnCode().replaceAll("[a-zA-Z]", "");
                    int utellength = ul.length();
                    String u = "";
                    for (int i = 0; i < utellength; i++) {
                        u = u + "0";
                    }
                    BigInteger utel = new BigInteger(ul);
                    BigInteger untel = new BigInteger(String.valueOf("1"));
                    utel = utel.add(untel);
                    //NumberFormat去格式化
                    NumberFormat nf = new DecimalFormat(u);
                    String str = nf.format(utel);
                    String enCode = parentEntity.getEnCode();
                    entity.setEnCode(enCode.charAt(0) + str);
                } else {
                    entity.setEnCode(parentEntity.getEnCode() + "01");
                }
            } else {
                setCode(parentEntity);
            }
            organizeService.updateById(entity);
        }
    }

    public void setOrganizedTree() {
        List<OrganizeEntity> listOrgan = organizeService.getList();
        List<String> collectCompany = listOrgan.stream().filter(i -> COMPANY.equals(i.getCategory())).map(v -> v.getId()).collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(listOrgan)) {
            for (OrganizeEntity item : listOrgan) {
                String organizeIdTree = organizeService.getOrganizeIdTreeALL(item);
                List<String> listTree = Arrays.asList(organizeIdTree.split(","));
                List<String> collectOrg = listTree.stream().filter(collectCompany::contains).collect(Collectors.toList());
                String organizeId = "0";
                if (!ObjectUtil.isEmpty(collectOrg)) {
                    organizeId = collectOrg.get(collectOrg.size() - 1);
                }
                item.setOrganizeIdTree(organizeIdTree);
                item.setOrganizeId(organizeId);
            }
            organizeService.updateBatchById(listOrgan);
        }
    }

    /**
     * 重载setOrganizedTree方法，按企业ID获取组织列表，设置祖宗组织id
     * @param corpId
     */
    public void setOrganizedTree(String corpId) {
        List<SynThirdInfoEntity> listByCrop = synThirdInfoService.getListByCrop(THIRD_TYPE_QY, DATA_TYPE_ORG, corpId);
        List<String> idList = listByCrop.stream().map(SynThirdInfoEntity::getSystemObjectId).collect(Collectors.toList());
        List<OrganizeEntity> listOrgan = organizeService.getListAll(idList, null);
        List<String> collectCompany = listOrgan.stream().filter(i -> COMPANY.equals(i.getCategory())).map(v -> v.getId()).collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(listOrgan)) {
            for (OrganizeEntity item : listOrgan) {
                String organizeIdTree = organizeService.getOrganizeIdTreeALL(item);
                List<String> listTree = Arrays.asList(organizeIdTree.split(","));
                List<String> collectOrg = listTree.stream().filter(collectCompany::contains).collect(Collectors.toList());
                String organizeId = "0";
                if (!ObjectUtil.isEmpty(collectOrg)) {
                    organizeId = collectOrg.get(collectOrg.size() - 1);
                }
                item.setOrganizeIdTree(organizeIdTree);
                item.setOrganizeId(organizeId);
            }
            organizeService.updateBatchById(listOrgan);
        }
    }
}
